#pragma once
#include "Types.h"
#include "ISceneNode.h"
#include "SceneNodeProperties.h"
#include "util/Shared_ptr.h"



namespace Boon
{
namespace Rendering
{
	class Scene;


	class BOON_API SceneNode : public ISceneNode
	{
	protected:
		typedef std::vector<ISceneNodeStrong>				VecSceneNodes;
		typedef std::map<std::size_t, IObserverRendering*>	MapObserver;

	public:
		static const uint_32				INVALID_OBSERVER_ID = 0xFFFFFFFF; 		/*!< used to identify an illegal registerObserver operation */

		SceneNode();
		SceneNode( GameObjectWeak go, ISceneNode* parent = nullptr );
		SceneNode( GameObjectID id, const std::string& name, RenderPass rp, ISceneNode* parent = nullptr );
		~SceneNode();

		virtual void					Init( Renderer& renderer );

		virtual const SceneNodeProperties* const		Get() const;

		virtual void					SetTransform( const Matrix44& toWorld, const Matrix44& fromWorld );

		virtual bool					IsVisible( Scene* scene ) const;

		virtual bool					AddChild( const ISceneNodeStrong& child );

		/*! \brief		Removes a child and returns strong reference to it
			\param		child - ID of child to remove
			\return		ISceneNodeStrong - On Success Strong reference that is instance
						holder of removed child otherwise empty ISceneNodeStrong()
		*/
		virtual ISceneNodeStrong		RemoveChild( const GameObjectID& child );

		virtual bool					Update();

		virtual bool					PreRender( Scene* scene );

		virtual bool					Render( Scene* scene );

		virtual bool					RenderChildren( Scene* scene );

		virtual bool					PostRender( Scene* scene );

		virtual void					OnRestore();

		virtual void					OnLostDevice();

		/*! \brief		Registers a observer to rendering process
			\param		observer - Reference to observer
			\return		Boon::uint_32 - A ID on success or SecneNode::INVALID_OBSERVER_ID
		*/
		virtual uint_32					RegisterObserver( IObserverRendering* observer );

		/*! \brief		Removes a observer with id returned by registerObserver()
			\param		observerID - id of observer to remove
			\return		bool - True on successful removal
		*/
		virtual bool					RemoveObserver( uint_32 observerID );

	protected:
		virtual void					SetParent( ISceneNode* parent );
		virtual ISceneNode*				GetParent() const;


		VecSceneNodes&					GetChilds();
		inline void						NotifyObserver( void (IObserverRendering::*observerCallback)( const InfoObserverRendering& ) );


	private:

		MapObserver						m_Observer;			/*!< Used to hold references to all observers registered to this scene node */
		VecSceneNodes					m_Childs;
		SceneNodeProperties				m_Properties;
		ISceneNode*						m_Parent;

		friend class Scene;
	};
}
}
